//! \file Dice.h
//! \brief The Dice class implements the complete dice set (and more) for
//! Dungeons and Dragons game rules.
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------
#ifndef dDICE_H_
#define dDICE_H_

#include <string>

//#ifdef __cplusplus
//  extern "C" {
//#endif

namespace std {

// =============================================================================
//! \typedef tROLL
//! \brief TODO: document
// -----------------------------------------------------------------------------
typedef signed int tROLL;


// =============================================================================
//! \enum eRollType
//! \brief TODO: comment
// -----------------------------------------------------------------------------
typedef enum
{
  eROLL_VALUE,    //!< A normal dice roll.
  eROLL_MINIMUM,  //!< The minimum value that could be produced by a roll.
  eROLL_MAXIMUM   //!< The maximum value that could be produced by a roll.
} eRollType;


// =============================================================================
//! \enum eTokenType
//! \brief TODO: comment
// -----------------------------------------------------------------------------
typedef enum
{
  eTOKEN_TYPE_UNKNOWN,    //!< The token is unknown or unidentified.
  eTOKEN_TYPE_END,        //!< The token is an expression terminator.
  eTOKEN_TYPE_DELIMITER,  //!< The token is an expression delimiter.
  eTOKEN_TYPE_VARIABLE,   //!< TODO: remove, we don't support variables.
  eTOKEN_TYPE_NUMBER      //!< The token is a numeric value.
} eTokenType;


// TODO: document
#define mROLL(Expression)     std::Dice::getSingleton()->roll(Expression)
#define mROLL_MIN(Expression) std::Dice::getSingleton()->roll(Expression, eROLL_MINIMUM)
#define mROLL_MAX(Expression) std::Dice::getSingleton()->roll(Expression, eROLL_MAXIMUM)


// TODO: document
class Dice
{
  public:
    static const tROLL ERROR_ROLLING = -32768;
    static Dice* getSingleton();
    tROLL roll(string Expression, eRollType Type = eROLL_VALUE);

  private:

    // Singleton
    static Dice* m_pDice;               // (Singleton) Instance.
    Dice();                             // (Singleton) Private so that it can  not be called
    Dice(Dice const&);                  // (Singleton) Don't implement.
    Dice& operator=(Dice const&);       // (Singleton) Don't implement.

    // Members
    eRollType m_RollType;
    eTokenType m_TokenType;
    char m_Token[80];
    const char *m_pExpression;

    // Roll Types
    tROLL roll(tROLL Number, tROLL Faces = 1);

    // Token Processing
    void getToken(void);
    bool isDelimiter(char Value);

    // Evaluation Levels
    void evaluateLevel1(tROLL &Result);
    void evaluateLevel2(tROLL &Result);
    void evaluateLevel3(tROLL &Result);
    void evaluateLevel4(tROLL &Result);
    void evaluateLevelFinal(tROLL &Result);
};


} // namespace std

//  #ifdef __cplusplus
//    }
//  #endif

#endif // dDICE_H_
